package com.junmoo.www.tool;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.util.*;
import java.util.function.Function;
import java.util.zip.*;

public class JwtUtils {
    public static final long expiration = 5 * 60 ; //5分钟
    private static SignatureAlgorithm signatureAlgorithm=SignatureAlgorithm.HS512;
    private static String secret="123456";

    /**
     *
     * @param claims
     * @param subject
     * @param expiration
     * @return
     */
    public static String generateToken(Map<String, Object> claims, String subject,Long expiration) {
        return Jwts.builder()
                .setClaims(claims) // 负载
                .setSubject(subject) // 主体
                .setIssuedAt( Date.from(Instant.now()) ) // 签发时间
                .setExpiration( Date.from( Instant.now().plusSeconds( expiration ) )  ) // 过期时间
                .signWith(signatureAlgorithm, secret)
                .compact();
    }

    public static String generateToken(Map<String, Object> claims, String subject) {
        return generateToken(new HashMap<>(), subject,expiration);
    }

    public static String generateToken( String subject,Long expiration) {
        return generateToken(new HashMap<>(), subject,expiration);
    }

    public static String generateToken(String subject) {
        return generateToken(new HashMap<>(), subject,expiration);
    }

    public static Claims getAllClaims(String token) {
        try {
            return Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token) //会自动检查过期时间
                    .getBody();
        }catch (ExpiredJwtException e){
           return e.getClaims(); // 抛出异常后，再次获取Claims
        }
    }

    public  static <T> T getClaim(String token, Function<Claims, T> claimsResolver) {
        final Claims claims = getAllClaims(token);
        return claimsResolver.apply(claims);
    }
    public static Object getByKey(String token,String key) {
        return getClaim(token, claims ->claims.get(key) );
    }

    public static Date getExpirationDate(String token) {
        return getClaim(token, Claims::getExpiration);
    }
    public static String getSubject(String token) {
        return getClaim(token, Claims::getSubject);
    }

    public static Boolean isTokenExpired(String token) {
        final Date expiration = getExpirationDate(token);
        return expiration.before(new Date());
    }

    /**
     * 信息摘要 sha256 算法 加密，不可逆。
     * @param str
     * @return
     * @throws NoSuchAlgorithmException
     */
    public static String  getSha256(String str) throws NoSuchAlgorithmException {
        MessageDigest messageDigest = MessageDigest.getInstance("SHA-256");
        byte[] bytes = messageDigest.digest(str.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(bytes);

    }

    /**
     * deflate解压缩
     * @param inputString
     * @return
     * @throws IOException
     */
    public static String deflateUnCompress(String inputString) throws IOException {
        byte[] bytes = Base64.getDecoder().decode(inputString);
        if(bytes == null || bytes.length == 0){
            return null;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ByteArrayInputStream in = new ByteArrayInputStream(bytes);
        InflaterInputStream inflater = new InflaterInputStream(in);
        byte[] buffer = new byte[256];
        int n;
        while((n = inflater.read(buffer)) >= 0){
            out.write(buffer, 0, n);
        }
        return out.toString("utf-8");

    }

    /**
     * deflate压缩
     * @param original
     * @return
     * @throws IOException
     */
    public static String deflateCompress(String original) throws IOException {
        if(original == null || original.length() == 0){
            return null;
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        DeflaterOutputStream deflater = new DeflaterOutputStream(out);
        deflater.write(original.getBytes(StandardCharsets.UTF_8));
        deflater.close();
        out.close();
        return Base64.getEncoder().encodeToString(out.toByteArray());

    }

    /**
     * 转16进制字符串
     * @param b
     * @return
     */
    public static String byte2hex(byte[] b) { // 一个字节的数，
        if(b == null || b.length == 0){
            return null;
        }
        StringBuffer sb = new StringBuffer(b.length * 2);
        String tmp = "";
        for (int n = 0; n < b.length; n++) {
            // 整数转成十六进制表示
            tmp = (java.lang.Integer.toHexString(b[n] & 0XFF));
            if (tmp.length() == 1) {
                sb.append("0");
            }
            sb.append(tmp);
        }
        return sb.toString(); // 转成大写
    }


}
